package com.example.demo;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author adr
 */
public class ADBPortRegister {

    public ArrayList<Integer> freePort = new ArrayList<>();
    public ArrayList<Integer> busyPort = new ArrayList<>();
    public Map<String, Integer> map = new HashMap<>();
    private ThreadPoolExecutor executor;

    private static class H {
        private static ADBPortRegister instance = new ADBPortRegister();
    }

    public static ADBPortRegister get() {
        return H.instance;
    }

    private ADBPortRegister() {
        executor = new ThreadPoolExecutor(10, 20, 1, TimeUnit.HOURS, new ArrayBlockingQueue<>(10), r -> new Thread(r, "ADBPortRegister"));
    }

    public void init() {
        executor.execute(() -> {
            ServerSocket serverSocket = null;
            try {
                AdbManager.init();
                serverSocket = new ServerSocket(6666);
                while (true) {
                    Socket accept = serverSocket.accept();
                    async(accept);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    private void async(final Socket accept) {
        executor.execute(new ConnectTask(this, accept, executor));
    }

    public void disconnect(String ip) {
        String emName = AdbManager.findMatchDeviceNameDefault(ip);
        Integer port = map.get(emName);
        if (port != null) {
            freePort.remove(Integer.valueOf(port - 1));
            busyPort.remove(Integer.valueOf(port - 1));
        }
        map.remove(emName);
    }

    public int providePort() {
        if (freePort.size() == 0) {
            if (busyPort.size() > 0) {
                return busyPort.get(0);
            } else {
                return 0;
            }
        } else {
            Integer integer = freePort.remove(0);
            busyPort.add(integer);
            return integer;
        }
    }

    public void addFreePort(int port) {
        busyPort.remove(Integer.valueOf(port));
        freePort.add(port);
    }

    public String info() {
        String s = "free port:";
        for (Integer integer : freePort) {
            s += integer;
            s += "|";
        }
        if (s.endsWith("|")) {
            s = s.substring(0, s.length() - 1);
        }
        s += "\nbusy port:";
        for (Integer integer : busyPort) {
            s += integer;
            s += "|";
        }
        if (s.endsWith("|")) {
            s = s.substring(0, s.length() - 1);
        }
        return s;
    }
}
